   ' ****************************************************************

   ' ***  FFT09-01 *** POSITIVE FREQUENCY FFT ***

   'THIS PROGRAM ANALYZES TIME DOMAIN DATA WITH FRACTIONAL FREQUENCY

   'ANALYSIS.  IT SIMULATES THE PERFORMANCE REQUIRED FOR A FREQUENCY

   'ANALYZER AND INCLUDES THE LATEST PFFFT (FFT08-01).

   ' ****************************************************************

10 SCREEN 9, 1: COLOR 15, 1: CLS ' SETUP DISPLAY SCREEN

12 QX = 2 ^ 13: QI = 2 ^ 6: WSF = 1' MAX & NOM SIZE & S.F. CORR

14 N = 12: X0 = 50: Y0 = 300

16 Q = 2 ^ N: N1 = N - 1: Q1 = Q - 1: Q2 = Q / 2: Q3 = Q2 - 1: Q4 = Q / 4: Q5 = Q4 - 1

18 Q8 = Q / 8: Q9 = Q8 - 1: Q34 = Q2 + Q4: Q16 = Q / 16

20 DIM Y(QX), C(QX), S(QX), KC(Q2), KS(Q2)

22 PI = 3.14159265358979#: P2 = PI * 2: K1 = P2 / Q

24 IOFLG = 2: WTFLG = 1 ' SET TO GRAPHIC DISPLAY AND NO WEIGHTING

26 XSF = 500 / Q2: YSF = WSF * 300 * Q / QI: SK1 = 1

32 FOR I = 0 TO Q3: KC(I) = COS(I * K1): KS(I) = SIN(I * K1): NEXT I

34 '    ************************************************

36 '    ********   MAIN MENU (ANALYZER SETUP)   ********

38 '    ************************************************

40 CLS : LOCATE 2, 30: PRINT "ANALYZER SETUP MENU"

42 LOCATE 6, 1' DISPLAY MENU

60 PRINT SPC(5); "1 = ANALYZE FULL DATA ARRAY": PRINT

62 PRINT SPC(5); "2 = ANALYZE 1/2 DATA ARRAY": PRINT

64 PRINT SPC(5); "3 = ANALYZE 1/4 DATA ARRAY": PRINT

66 PRINT SPC(5); "4 = ANALYZE 1/8 DATA ARRAY": PRINT

68 PRINT SPC(5); "5 = ANALYZE 1/16 DATA ARRAY": PRINT

72 PRINT SPC(5); "7 = CHANGE SYSTEM SETUP": PRINT

74 PRINT SPC(5); "9 = END": PRINT

78 PRINT SPC(10); "MAKE SELECTION: ";

80 A$ = INKEY$: IF A$ = "" THEN 80

82 PRINT A$

90 A = VAL(A$): ON A GOSUB 850, 860, 870, 880, 890, 94, 970, 94, 999

92 GOTO 40

94 RETURN

98  '         *****************************

100 '         ***   FORWARD TRANSFORM   ***

102 '         *****************************

106 '          ***  TRANSFORM STAGE 1  ***

108 T9 = TIMER

110 C(0) = (S(0) + S(Q2)) / 2: C(1) = (S(0) - S(Q2)) / 2

112 FOR I = 1 TO Q3: I2 = 2 * I: INDX = 0 ' BIT REVERSE DATA ADDRESSES

114 FOR J = 0 TO N1: IF I AND 2 ^ J THEN INDX = INDX + 2 ^ (N - 2 - J)

116 NEXT J

118 C(I2) = (S(INDX) + S(INDX + Q2)) / 2: C(I2 + 1) = (S(INDX) - S(INDX + Q2)) / 2

120 NEXT I

122 FOR I = 0 TO Q1: S(I) = 0: NEXT I

'       *********  REMAINING STAGES  **********

124 FOR M = 1 TO N1: QP = 2 ^ M: QPI = 2 ^ (N1 - M)

126  FOR K = 0 TO QPI - 1

128   FOR J = 0 TO QP / 2: J0 = J + (2 * K * QP): J1 = J0 + QP: K2 = QPI * J

130   JI = J1 - (2 * J)

132   CTEMP1 = C(J0) + C(J1) * KC(K2) - S(J1) * KS(K2)

134   STEMP1 = S(J0) + C(J1) * KS(K2) + S(J1) * KC(K2)

136   CTEMP2 = C(J0) - C(J1) * KC(K2) + S(J1) * KS(K2)

138   S(JI) = (C(J1) * KS(K2) + S(J1) * KC(K2) - S(J0)) / 2

140   C(J0) = CTEMP1 / 2: S(J0) = STEMP1 / 2: C(JI) = CTEMP2 / 2

142   NEXT J

144  NEXT K

146 NEXT M

148 FOR J = Q2 + 1 TO Q1: C(J) = 0: S(J) = 0: NEXT J

150 T9 = TIMER - T9

152 ON IOFLG GOSUB 300, 350 ' DISPLAY SPECTRUM

RETURN



'         ********************************

'         *******   PRINT OUTPUT   *******

300 '     ********************************

160 FOR Z = 0 TO Q5' PRINT OUTPUT

162 PRINT USING "####"; Z; : PRINT "   ";

164 PRINT USING "+##.#####"; SK1 * C(Z); : PRINT "   ";

166 PRINT USING "+##.#####"; SK1 * S(Z); : PRINT "     ";

168 PRINT USING "####"; Z + Q4; : PRINT "   ";

170 PRINT USING "+##.#####"; SK1 * C(Z + Q4); : PRINT "   ";

172 PRINT USING "+##.#####"; SK1 * S(Z + Q4)

174 NEXT Z

176 PRINT "T = "; T9: INPUT "ENTER TO CONTINUE"; A$

178 RETURN



    ' **********************************

    ' *         PLOT SPECTRUM          *

    ' **********************************

350 CLS : LINE (X0 - 1, 50)-(X0 - 1, Y0 + 1)' DRAW Y AXIS

352 LINE (X0 + 500, Y0 + 1)-(X0, Y0 + 1)' DRAW X AXIS

354 FOR I = 0 TO Q2: XI = X0 + XSF * I

356 YI = Y0 - YSF * SQR(C(I) ^ 2 + S(I) ^ 2)' FIND RSS OF COMPLEX DATA

358 LINE (XI, YI)-(XI, YI)

360 NEXT I

362 RETURN



    ' **********************************

    ' *      GENERATE SINE WAVE        *

    ' **********************************

400 FOR I = 0 TO QDT: C(I) = 0: S(I) = SIN(F9 * K1 * I): NEXT

402 FOR I = QDT TO Q: C(I) = 0: S(I) = 0: NEXT

404 RETURN



'     **********************************

600 ' ***     SPECTRUM ANALYZER      ***

    ' **********************************

602 CLS : PRINT : PRINT

604 PRINT SPC(20); "PREPARING DATA - PLEASE WAIT"

610 GOSUB 400 ' GENERATE SINUSOID

620 GOSUB 100 ' ANALYZE SPECTRUM

624 REPT = 0  ' RESET REPEAT FLAG

626 PRINT : PRINT "ANY KEY TO CONTINUE";

628 A$ = INKEY$: IF A$ = "" THEN 628' WAIT USER INPUT

630 IF ASC(A$) = 0 THEN GOSUB 650' CURSOR HAS LEADING ZERO

632 IF REPT = 1 THEN 620 ' ANALYZE SPECTRUM AGAIN

634 RETURN ' BACK TO MAIN MENU



650 ' ***  HANDLE CURSOR KEYS  ***

652 A = ASC(RIGHT$(A$, 1)) ' WHICH CURSOR

654 IF A < 75 OR A > 77 OR A = 76 THEN 669 ' NOT A CURSOR KEY      

656 IF A = 75 THEN F8 = F8 - .1 ' INC FREQUENCY

658 IF A = 77 THEN F8 = F8 + .1 ' DEC. FREQUENCY

660 F9 = F8 * Q / QI' SCALE FOR CURRENT ARRAY SIZE

662 GOSUB 400 ' GENERATE NEW SINUSOID

664 REPT = 1 ' SET REPEAT FLAG

669 RETURN ' DO IT AGAIN SAM



800 ' *********************************************

    ' *    SETUP FRACTIONAL FREQUENCY ANALYZER    *

    ' *********************************************

850 N = 6: N1 = 5: Q = 2 ^ N: QDT = Q - 1' SET NEW ARRAY SIZE

852 Q2 = Q / 2: Q3 = Q2 - 1: Q4 = Q / 4: Q5 = Q4 - 1: Q8 = Q / 8: Q9 = Q8 - 1

853 Q16 = Q / 16: Q34 = Q2 + Q4

854 F8 = 16: F9 = F8 * Q / QI: K1 = P2 / Q' NEW TWIDDLES

856 FOR I = 0 TO Q3: KC(I) = COS(K1 * I): KS(I) = SIN(K1 * I): NEXT

857 XSF = 500 / Q2: YSF = WSF * 300 * Q / QI

858 GOSUB 600 ' ANALYZE SPECTRUM

859 RETURN ' BACK TO MAIN MENU



860 N = 7: N1 = 6: Q = 2 ^ N: QDT = Q / 2 - 1

862 GOTO 852



870 N = 8: N1 = 7: Q = 2 ^ N: QDT = Q / 4 - 1

872 GOTO 852



880 N = 9: N1 = 8: Q = 2 ^ N: QDT = Q / 8 - 1

882 GOTO 852



890 N = 10: N1 = 9: Q = 2 ^ N: QDT = Q / 16 - 1

892 GOTO 852



    '  ***********************

    '  *     SYSTEM SETUP    *

    '  ***********************

970 CLS : PRINT "SYSTEM SETUP MENU"

972 PRINT "USE GRAPHIC DISPLAY? (Y/N)";

980 A$ = INKEY$: IF A$ = "" THEN 980

982 IF A$ = "y" OR A$ = "Y" THEN IOFLG = 2 ELSE IOFLG = 1

988 RETURN

' **********

999 STOP



